<html>
  <head>
    <title>websocket</title>
    <meta charset="utf-8" />
  </head>
  <body>
	<div style="font-weight:blod">依赖</div>
	<xmp style="background: #f6f6f6;">
	<!--websocket依赖-->
	<dependency>
	   <groupId>org.springframework.boot</groupId>
	   <artifactId>spring-boot-starter-websocket</artifactId>
	</dependency>
	</xmp>
	<div style="font-weight:blod">注入</div>
	<xmp style="background: #f6f6f6;">
	import org.springframework.context.annotation.Bean;
	import org.springframework.context.annotation.Configuration;
	import org.springframework.web.socket.server.standard.ServerEndpointExporter;

	@Configuration
	public class WebSocketConfig {
		@Bean
		public ServerEndpointExporter serverEndpointExporter(){
			return new ServerEndpointExporter();
		}
	}
	</xmp>
	<div style="font-weight:blod">申明</div>
	<xmp style="background: #f6f6f6;">
		import org.slf4j.Logger;
		import org.slf4j.LoggerFactory;
		import org.springframework.stereotype.Component;

		import javax.websocket.*;
		import javax.websocket.server.PathParam;
		import javax.websocket.server.ServerEndpoint;
		import java.io.IOException;
		import java.util.LinkedHashMap;
		import java.util.Map;

		/*
		* @ServerEndpoint(value = "/websocket")：设置WebSocket请求路径
		* @Component：注册到spring容器中
		* */
		@ServerEndpoint(value = "/websocket/{userId}")
		@Component
		public class MyWebSocket {
			/*
			* 静态全局变量（类变量）：
			*       webSocketMap：保存所有在线socket连接
			*       count：记录当前在线数目
			* 类成员变量：
			*       session：当前连接（每个websocket连入都会创建一个MyWebSocket实例）
			*       log：日志
			* 类成员方法：
			*       onOpen()：处理连接建立
			*       onMessage()：接受消息
			*       onError()：处理错误
			*       onClose()：处理连接关闭
			*       sendMessage():发送消息
			*       broadcast():广播消息
			*       addCount():操作count++，使用synchronized确保线程安全
			*       reduceCount():操作count--，使用synchronized确保线程安全
			* */
			private static Map<String,MyWebSocket> webSocketMap = new LinkedHashMap<>();
			private static int count=0;
			private Session session;
			private Logger log = LoggerFactory.getLogger(this.getClass());
			@OnOpen
			public void onOpen(Session session,@PathParam("userId") String userId){
				this.session=session;
				webSocketMap.put(userId,this);
				addCount();
				log.info("新的连接（{}）加入",userId);
			}
			@OnMessage
			public void onMessage(String message,Session session,@PathParam("userId") String userId){
				log.info("收到客户端（{}）的消息：{}",userId,message);
				try{
					this.sendMessage("收到消息："+message);
				}catch (Exception e){
					e.printStackTrace();
				}
			}
			@OnError
			public void onError(Throwable error,Session session,@PathParam("userId") String userId){
				log.info("（{}）发生错误,{}",userId,error.getMessage());
			}
			@OnClose
			public void onClose(@PathParam("userId") String userId){
				webSocketMap.remove(userId);
				reduceCount();
				log.info("（{}）连接关闭",userId);
			}
			public void sendMessage(String message) throws IOException {
				this.session.getBasicRemote().sendText(message);
			}
			public static void broadcast(){
				MyWebSocket.webSocketMap.forEach((k,v)->{
					try{
						v.sendMessage("这是一条测试广播");
					}catch (Exception e){
					}
				});
			}
			public static synchronized void addCount(){
				MyWebSocket.count++;
			}
			public static synchronized void reduceCount(){
				MyWebSocket.count--;
			}
		}
	</xmp>
	
    <button onclick="sendMessage()">websocket发送消息</button>
    <script>
		/*
		* let webSocket = new WebSocket("ws://localhost:8888/websocket");
		*	webSocket.readyState：
		*		CONNECTING==0（正在连接）
		*		OPEN==1（连接成功，可以通信了）
		*		CLOSING==2（连接正在关闭）
		*		CLOSED==3（连接已经关闭，或者打开连接失败）
		*/
		let socket = new WebSocket("ws://localhost:8888/websocket/111");
		/*
		*连接成功后的回调函数
		*写法二：
		*	webSocket.addEventListener('open',function (event){});
		*/
		socket.onopen = event => {
			console.log("连接成功后的回调函数执行：");
			console.log(event);
		};
		/*
		*连接关闭后的回调函数
		*写法二：
		*	webSocket.addEventListener('close',function (event){});
		*/
		socket.onclose = event => {
			console.log("连接关闭后的回调函数：");
			console.log(event);
		};
		/*
		*报错时的回调函数
		*写法二：
		*	webSocket.addEventListener('error',function (event){});
		*/
		socket.onerror = event => {
			console.log("报错时的回调函数：");
			console.log(event);
		};
		/*
		*收到服务器数据后的回调函数
		*写法二：
		*	webSocket.addEventListener('message',function (event){});
		*/
		socket.onmessage = event => {
			console.log("收到服务器数据后的回调函数：");
			console.log(event);
		};


		function sendMessage() {
		if (socket.readyState === 1) socket.send("这是一个测试数据");
		else alert("尚未建立websocket连接");
		}
    </script>
  </body>
</html>